import { Injectable, Logger } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository, DataSource, QueryRunner } from "typeorm";
import { CharacterLocationEntity } from "../entities/character-location.entity";
import { CharacterEntity } from "../entities/character.entity";
import { CharacterAttributeEntity } from "../entities/character-attribute.entity";
import { CharacterDetailedAttributeEntity } from "../entities/character-detailed-attribute.entity";
import { CharacterSkillEntity } from "../entities/character-skill.entity";
import { CharacterSkillService } from "./character-skill.service";
import { SocialRelationEntity } from "../entities/social-relation.entity";
import { CharacterReligionEntity } from "../entities/character-religion.entity";
import { CharacterResidenceEntity } from "../entities/character-residence.entity";
import { CharacterStoneEntity } from "../entities/character-stone.entity";
import { CharacterResourcesEntity } from "../entities/character-resources.entity";
import { CharacterInventoryEntity } from "../entities/character-inventory.entity";
import { CharacterMountEntity } from "../entities/character-mount.entity";
import { RedisService } from "../services/redis.service";
import { DeputyGeneralService } from "./deputy-general.service";
import { CharacterAttributeService } from "./character-attribute.service";
import { LevelExperienceEntity } from "../entities/level-experience.entity";
import { CharacterSinewClaimEntity } from "../entities/character-sinew-claim.entity";
import { CharacterSinewWindowClaimEntity } from "../entities/character-sinew-window-claim.entity";

@Injectable()
export class CharacterService {
  private readonly logger = new Logger(CharacterService.name);

  constructor(
    @InjectRepository(CharacterEntity)
    private characterRepository: Repository<CharacterEntity>,
    @InjectRepository(CharacterAttributeEntity)
    private attributeRepository: Repository<CharacterAttributeEntity>,
    @InjectRepository(CharacterDetailedAttributeEntity)
    private detailedAttributeRepository: Repository<CharacterDetailedAttributeEntity>,
    @InjectRepository(CharacterSkillEntity)
    private skillRepository: Repository<CharacterSkillEntity>,
    @InjectRepository(SocialRelationEntity)
    private socialRelationRepository: Repository<SocialRelationEntity>,
    @InjectRepository(CharacterReligionEntity)
    private religionRepository: Repository<CharacterReligionEntity>,
    @InjectRepository(CharacterResidenceEntity)
    private residenceRepository: Repository<CharacterResidenceEntity>,
    @InjectRepository(CharacterStoneEntity)
    private stoneRepository: Repository<CharacterStoneEntity>,
    @InjectRepository(CharacterResourcesEntity)
    private resourcesRepository: Repository<CharacterResourcesEntity>,
    @InjectRepository(CharacterInventoryEntity)
    private inventoryRepository: Repository<CharacterInventoryEntity>,
    @InjectRepository(CharacterLocationEntity)
    private characterLocationRepository: Repository<CharacterLocationEntity>,
    @InjectRepository(CharacterMountEntity)
    private characterMountRepository: Repository<CharacterMountEntity>,
    @InjectRepository(LevelExperienceEntity)
    private levelExperienceRepository: Repository<LevelExperienceEntity>,
    private dataSource: DataSource,
    private redisService: RedisService,
    private deputyGeneralService: DeputyGeneralService,
    private characterAttributeService: CharacterAttributeService,
    private readonly characterSkillService: CharacterSkillService
  ) {}

  /**
   * 根据ID获取角色基本信息
   */
  async getCharacterById(characterId: number) {
    return await this.characterRepository.findOne({
      where: { id: characterId },
    });
  }

  /**
   * 计算转职对应的等级上限：未转100，1转120，2转140，3转及以上160
   */
  private getLevelCap(transCount: number): number {
    if (!transCount || transCount <= 0) return 100;
    if (transCount === 1) return 120;
    if (transCount === 2) return 140;
    return 160;
  }

  /**
   * 通用经验结算（基于“剩余所需经验exp”模型）
   * - 支持溢出多级升级
   * - 应用等级上限
   * - 每次升级调用属性点处理
   * - 返回最终等级、剩余所需经验、升级次数
   */
  async applyExperience(
    characterId: number,
    expGained: number,
    options?: { queryRunner?: QueryRunner }
  ): Promise<{ newLevel: number; newExp: number; levelUpTimes: number }> {
    const manager = options?.queryRunner
      ? options.queryRunner.manager
      : this.characterRepository.manager;

    const character = await manager.findOne(CharacterEntity, {
      where: { id: characterId },
    });
    if (!character) {
      throw new Error("角色不存在");
    }

    const levelCap = this.getLevelCap(character.trans || 0);

    let level = character.lvl;
    let expRemaining = character.exp - Math.max(0, expGained); // exp为“还需经验”，获得经验用于抵扣
    let levelUpTimes = 0;

    while (expRemaining <= 0 && level < levelCap) {
      levelUpTimes += 1;
      level += 1;
      const overflow = -expRemaining; // 溢出经验进入下一级
      // 从level_experience表取下一级所需经验
      const levelExpRow = await manager.findOne(LevelExperienceEntity, {
        where: { level },
      });
      const nextNeed = levelExpRow?.experience
        ? Number(levelExpRow.experience)
        : level * 1000;
      expRemaining = nextNeed - overflow;

      // 每升一级：处理属性点
      await this.characterAttributeService.handleLevelUp(characterId, level);
    }

    // 到达上限后不再累计，剩余所需经验不为负
    if (level >= levelCap && expRemaining < 0) {
      expRemaining = 0;
    }

    await manager.update(
      CharacterEntity,
      { id: characterId },
      {
        lvl: level,
        exp: expRemaining,
        updated_at: new Date(),
      }
    );

    return { newLevel: level, newExp: expRemaining, levelUpTimes };
  }

  /**
   * 按体力值消耗：减少体力（sinew）。体力不足时报错。
   */
  async decreaseSinew(
    characterId: number,
    cost: number,
    options?: { queryRunner?: QueryRunner }
  ): Promise<void> {
    if (cost <= 0) return;
    const manager = options?.queryRunner
      ? options.queryRunner.manager
      : this.attributeRepository.manager;
    const attr = await manager.findOne(CharacterAttributeEntity, {
      where: { characterId },
    });
    if (!attr) {
      throw new Error("角色属性不存在");
    }
    const current = Number(attr.sinew || 0);
    if (current < cost) {
      throw new Error(`体力不足，需要${cost}点体力值`);
    }
    await manager.update(
      CharacterAttributeEntity,
      { characterId },
      { sinew: current - cost, updated_at: new Date() }
    );
  }

  /**
   * 使用体力丹：gid=82，每日最多4次，每次+50体力，受等级区间上限限制
   */
  async useSinewPotion(
    characterId: number,
    gid: number
  ): Promise<{ msg: string }> {
    if (gid !== 82) {
      throw new Error("不是体力丹");
    }

    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();
    try {
      const character = await queryRunner.manager.findOne(CharacterEntity, {
        where: { id: characterId },
      });
      if (!character) throw new Error("角色不存在");

      // 每日次数限制（4次）：使用 Redis 计数 或 简化用 attributes.updated_at 天判断 + count 表
      const key = `sinew:potion:${characterId}:${new Date()
        .toISOString()
        .slice(0, 10)}`;
      const used = Number((await this.redisService.get(key)) || 0);
      if (used >= 4) {
        throw new Error("今天体力丹使用次数已达上限");
      }

      // 消耗背包中体力丹1个
      const inv = await queryRunner.manager.findOne(CharacterInventoryEntity, {
        where: { characterId, itemId: gid },
      });
      if (!inv || (inv.num || 0) <= 0) {
        throw new Error("没有体力丹");
      }
      const newNum = (inv.num || 0) - 1;
      await queryRunner.manager.update(
        CharacterInventoryEntity,
        { id: inv.id },
        newNum > 0
          ? { num: newNum, updated_at: new Date() }
          : { num: 0, status: 0, updated_at: new Date() }
      );

      // 计算体力上限
      const attr = await queryRunner.manager.findOne(CharacterAttributeEntity, {
        where: { characterId },
      });
      if (!attr) throw new Error("角色属性不存在");
      const maxSinew = this.getSinewCapByLevel(character.lvl);
      if ((attr.sinew || 0) >= maxSinew) {
        throw new Error("体力已满，无法使用体力丹");
      }
      const inc = 50;
      const nextVal = Math.min(maxSinew, (attr.sinew || 0) + inc);
      await queryRunner.manager.update(
        CharacterAttributeEntity,
        { characterId },
        { sinew: nextVal, updated_at: new Date() }
      );

      await queryRunner.commitTransaction();
      await this.redisService.set(key, String(used + 1), 24 * 3600);
      return { msg: `体力+${nextVal - (attr.sinew || 0)}` };
    } catch (e: any) {
      await queryRunner.rollbackTransaction();
      throw e;
    } finally {
      await queryRunner.release();
    }
  }

  /**
   * 每日在线30分钟领取体力：每日一次，按固定增量增加（不超过等级上限）
   */
  async claimDailySinew(characterId: number): Promise<{ msg: string }> {
    const today = new Date().toISOString().slice(0, 10);

    // 数据库记录校验
    const exists = await this.dataSource.manager.findOne(
      CharacterSinewClaimEntity,
      { where: { characterId, claimDate: today } }
    );
    if (exists) throw new Error("今天已领取过体力");

    const character = await this.characterRepository.findOne({
      where: { id: characterId },
    });
    if (!character) throw new Error("角色不存在");

    const attr = await this.attributeRepository.findOne({
      where: { characterId },
    });
    if (!attr) throw new Error("角色属性不存在");

    const maxSinew = this.getSinewCapByLevel(character.lvl);
    const before = Number(attr.sinew || 0);
    if (before >= maxSinew) {
      // 体力已满也记为已领取以防重复
      const rec = new CharacterSinewClaimEntity();
      rec.characterId = characterId;
      rec.claimDate = today;
      rec.created_at = new Date();
      rec.updated_at = new Date();
      await this.dataSource.manager.save(rec);
      return { msg: "体力已满" };
    }

    // 每日增量 = 当前角色等级值
    const increment = Math.max(1, Number(character.lvl || 1));
    const after = Math.min(maxSinew, before + increment);
    await this.attributeRepository.update(
      { characterId },
      { sinew: after, updated_at: new Date() }
    );
    const rec = new CharacterSinewClaimEntity();
    rec.characterId = characterId;
    rec.claimDate = today;
    rec.created_at = new Date();
    rec.updated_at = new Date();
    await this.dataSource.manager.save(rec);
    return { msg: `体力+${after - before}` };
  }

  /**
   * 等级对应体力上限
   */
  private getSinewCapByLevel(level: number): number {
    if (level < 15) return 200; // 若低于表内起点，给最小档
    if (level <= 29) return 200;
    if (level <= 39) return 230;
    if (level <= 49) return 260;
    if (level <= 59) return 290;
    if (level <= 69) return 320;
    if (level <= 79) return 350;
    if (level <= 89) return 380;
    if (level <= 99) return 410;
    if (level <= 109) return 440;
    if (level <= 119) return 470;
    if (level <= 129) return 500;
    if (level <= 139) return 530;
    if (level <= 149) return 560;
    if (level <= 159) return 590;
    return 620; // 160级
  }

  /**
   * 对外暴露的体力上限计算
   */
  getSinewCap(level: number): number {
    return this.getSinewCapByLevel(level);
  }

  /**
   * 判断当日是否已领取在线体力（1374）
   */
  async hasClaimedDailySinew(characterId: number): Promise<boolean> {
    const today = new Date().toISOString().slice(0, 10);
    const existing = await this.dataSource.manager.findOne(
      CharacterSinewClaimEntity,
      { where: { characterId, claimDate: today } }
    );
    return !!existing;
  }

  /**
   * 返回当前时间窗口: 'noon' | 'evening' | null
   */
  getCurrentSinewWindow(): "noon" | "evening" | null {
    const now = new Date();
    const minutes = now.getHours() * 60 + now.getMinutes();
    const noonStart = 11 * 60 + 30;
    const noonEnd = 13 * 60 + 30;
    const eveStart = 19 * 60 + 30;
    const eveEnd = 21 * 60 + 30;
    if (minutes >= noonStart && minutes <= noonEnd) return "noon";
    if (minutes >= eveStart && minutes <= eveEnd) return "evening";
    return null;
  }

  /**
   * 判断当前窗口是否已领取体力（1375）
   * 不在窗口范围内，视为无需领取，返回 true
   */
  async hasClaimedWindowSinew(characterId: number): Promise<boolean> {
    const window = this.getCurrentSinewWindow();
    if (!window) return true; // 不在时段默认返回已领（前端 happy=1）
    const today = new Date().toISOString().slice(0, 10);
    const existing = await this.dataSource.manager.findOne(
      CharacterSinewWindowClaimEntity,
      { where: { characterId, claimDate: today, window } }
    );
    return !!existing;
  }

  /**
   * 领取时间段体力：中午(11:30-13:30) or 晚上(19:30-21:30)，每段每日各一次，+10体力
   */
  async claimWindowSinew(characterId: number): Promise<{ msg: string }> {
    const now = new Date();
    const today = now.toISOString().slice(0, 10);

    // 判断时间段
    const minutes = now.getHours() * 60 + now.getMinutes();
    const noonStart = 11 * 60 + 30;
    const noonEnd = 13 * 60 + 30;
    const eveStart = 19 * 60 + 30;
    const eveEnd = 21 * 60 + 30;
    let window: "noon" | "evening" | null = null;
    if (minutes >= noonStart && minutes <= noonEnd) window = "noon";
    else if (minutes >= eveStart && minutes <= eveEnd) window = "evening";
    if (!window) {
      throw new Error("不在可领取时间段");
    }

    // 幂等：检查是否已领取
    const exist = await this.dataSource.manager.findOne(
      CharacterSinewWindowClaimEntity,
      { where: { characterId, claimDate: today, window } }
    );
    if (exist) {
      throw new Error("本时段已领取");
    }

    // 计算并增加体力
    const character = await this.characterRepository.findOne({
      where: { id: characterId },
    });
    if (!character) throw new Error("角色不存在");
    const cap = this.getSinewCapByLevel(character.lvl);
    const attr = await this.attributeRepository.findOne({
      where: { characterId },
    });
    if (!attr) throw new Error("角色属性不存在");
    const before = Number(attr.sinew || 0);
    const after = Math.min(cap, before + 10);
    await this.attributeRepository.update(
      { characterId },
      { sinew: after, updated_at: new Date() }
    );

    const rec = new CharacterSinewWindowClaimEntity();
    rec.characterId = characterId;
    rec.claimDate = today;
    rec.window = window;
    rec.created_at = new Date();
    rec.updated_at = new Date();
    await this.dataSource.manager.save(rec);

    return { msg: `体力+${after - before}` };
  }

  /**
   * 获取角色完整信息（包括所有关联数据）
   */
  async getCharacterWithDetails(characterId: number) {
    return await this.characterRepository.findOne({
      where: { id: characterId },
      relations: [
        "attributes",
        "detailedAttributes",
        "skills",
        "socialRelations",
        "religion",
        "residence",
        "stones",
        "resources",
        "spouse",
        "master",
      ],
    });
  }

  /**
   * 更新角色名称
   */
  async updateCharacterName(characterId: number, name: string) {
    return await this.characterRepository.update(characterId, { name });
  }

  /**
   * 更新角色称号
   */
  async updateCharacterTitle(characterId: number, title: string) {
    return await this.characterRepository.update(characterId, { title });
  }

  /**
   * 获取角色完整信息 (c:1000)
   */
  async getCharacterInfo(characterId: number) {
    const character = await this.characterRepository.findOne({
      where: { id: characterId },
      relations: [
        "attributes",
        "detailedAttributes",
        "skills",
        "socialRelations",
      ],
    });

    if (!character) {
      return null;
    }

    // 构建返回数据结构，对齐test-www代码
    return {
      id: character.id,
      name: character.name,
      roleType: character.roleType,
      sex: character.sex,
      lvl: character.lvl,
      exp: character.exp,
      trans: character.trans,
      title: character.title || "",
      vip: character.vip,
      headImg: character.headImg,
      allowLogin: character.allowLogin,
      objType: character.objType,
      indexID: character.indexID,

      // 基础属性
      hp: character.attributes?.hp || 300,
      maxHp: character.attributes?.maxHp || 300,
      mp: character.attributes?.mp || 100,
      maxMp: character.attributes?.maxMp || 100,
      ap: character.attributes?.ap || 80,
      df: character.attributes?.df || 40,
      sp: character.attributes?.sp || 10,
      weight: character.attributes?.weight || 0,
      maxWeight: character.attributes?.maxWeight || 100,
      hyd: character.attributes?.hyd || 100,
      sinew: character.attributes?.sinew || 100,
      p: character.attributes?.p || 0,
      speedStr: character.attributes?.speedStr || "一",

      // 详细属性
      k_wl: character.detailedAttributes?.k_wl || 0,
      k_wei: character.detailedAttributes?.k_wei || 0,
      k_feng: character.detailedAttributes?.k_feng || 0,
      k_fa: character.detailedAttributes?.k_fa || 0,
      k_du: character.detailedAttributes?.k_du || 0,
      k_xi: character.detailedAttributes?.k_xi || 0,
      k_luan: character.detailedAttributes?.k_luan || 0,
      k_yao: character.detailedAttributes?.k_yao || 0,
      k_ll: character.detailedAttributes?.k_ll || 0,
      r_bj: character.detailedAttributes?.r_bj || 0,
      r_fj: character.detailedAttributes?.r_fj || 0,
      r_fz: character.detailedAttributes?.r_fz || 0,
      r_hb: character.detailedAttributes?.r_hb || 0,
      r_mf: character.detailedAttributes?.r_mf || 0,
      r_mz: character.detailedAttributes?.r_mz || 0,
      r_zm: character.detailedAttributes?.r_zm || 0,

      // 社交关系（从新的实体获取）
      religion:
        character.religion?.name === "无" ? undefined : character.religion,
      spouse:
        character.socialRelations?.spouseName === "无"
          ? undefined
          : { name: character.socialRelations.spouseName },
      master:
        character.socialRelations?.masterName === "无"
          ? undefined
          : { name: character.socialRelations.masterName },
      home: character.residence
        ? { name: character.residence.homeName }
        : { name: "新手村" },
      house: character.residence?.houseName
        ? { name: character.residence.houseName }
        : undefined,
      horse: character.residence?.horseName
        ? { name: character.residence.horseName }
        : undefined,

      // 技能信息 - 现在通过CharacterSkillService获取
      skill_1: 0, // 已废弃，通过1382指令获取
      skill_2: 0, // 已废弃，通过1382指令获取
      skill_3: 0, // 已废弃，通过1382指令获取
      skill_4: 0, // 已废弃，通过1382指令获取

      // 资源信息
      gold: character.resources?.gold || 0,
      silver: character.resources?.silver || 0,
      bdSilver: character.resources?.bdSilver || 0,
      fc: character.resources?.fc || 0,
      superHK: character.resources?.superHK || 0,
      tlz: character.resources?.tlz || 0,
      tlzs: character.resources?.tlzs || 0,
      vipBag: character.resources?.vipBag || 0,
    };
  }

  /**
   * 获取称号列表 (c:1001)
   */
  async getTitleList() {
    // 这里可以从称号表获取，暂时返回固定数据
    return [
      { id: 1, name: "新手", description: "初出茅庐的新手" },
      { id: 2, name: "勇士", description: "勇敢的战士" },
      { id: 3, name: "英雄", description: "受人尊敬的英雄" },
      { id: 4, name: "传奇", description: "传说中的强者" },
    ];
  }

  /**
   * 修改角色名称 (c:1003)
   */
  async modifyCharacterName(characterId: number, newName: string) {
    // 检查名称是否包含空格
    if (newName.includes(" ")) {
      throw new Error("用户名输入不能包含空格");
    }

    // 检查名称是否已存在
    const existingCharacter = await this.characterRepository.findOne({
      where: { name: newName },
    });

    if (existingCharacter && existingCharacter.id !== characterId) {
      throw new Error("该名称已被使用");
    }

    // 更新角色名称
    await this.characterRepository.update(characterId, { name: newName });

    return { name: newName };
  }

  /**
   * 修改角色名称（需要消耗改名卡）
   * @param characterId 角色ID
   * @param newName 新名称
   * @returns 修改结果
   */
  async modifyCharacterNameWithCard(characterId: number, newName: string) {
    // 使用事务确保改名和扣除改名卡的原子性
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

    try {
      // 1. 检查名称是否包含空格
      if (newName.includes(" ")) {
        throw new Error("用户名输入不能包含空格");
      }

      // 2. 检查名称是否已存在
      const existingCharacter = await queryRunner.manager.findOne(
        CharacterEntity,
        {
          where: { name: newName },
        }
      );

      if (existingCharacter && existingCharacter.id !== characterId) {
        throw new Error("该名称已被使用");
      }

      // 3. 检查角色是否存在
      const character = await queryRunner.manager.findOne(CharacterEntity, {
        where: { id: characterId },
      });

      if (!character) {
        throw new Error("角色不存在");
      }

      // 4. 检查是否需要改名卡（如果当前名字是"三国新人"则不需要）
      const needRenameCard = character.name !== "三国新人";

      if (needRenameCard) {
        // 检查背包中是否有改名卡：仅支持 ID 85（易名神符）
        const renameCard = await queryRunner.manager.findOne(
          CharacterInventoryEntity,
          {
            where: {
              characterId: characterId,
              itemId: 85, // 易名神符
              status: 1, // 正常状态（未使用）
            },
          }
        );

        if (!renameCard || renameCard.num < 1) {
          throw new Error("没有改名卡，无法改名");
        }

        // 扣除改名卡
        if (renameCard.num === 1) {
          // 如果只有一张，标记为已使用
          await queryRunner.manager.update(
            CharacterInventoryEntity,
            renameCard.id,
            {
              status: 0, // 标记为已使用
              updated_at: new Date(),
            }
          );
        } else {
          // 如果有多张，减少数量
          await queryRunner.manager.update(
            CharacterInventoryEntity,
            renameCard.id,
            {
              num: renameCard.num - 1,
              updated_at: new Date(),
            }
          );
        }
      }

      // 6. 更新角色名称
      await queryRunner.manager.update(CharacterEntity, characterId, {
        name: newName,
        updated_at: new Date(),
      });

      // 提交事务
      await queryRunner.commitTransaction();

      return {
        success: true,
        newName,
        message: needRenameCard
          ? "改名成功，已消耗改名卡"
          : "改名成功（首次改名免费）",
        consumedRenameCard: needRenameCard,
      };
    } catch (error) {
      // 回滚事务
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      // 释放查询运行器
      await queryRunner.release();
    }
  }

  /**
   * 获取副将战斗技能 (c:1006)
   */
  async getSubordinateBattleSkills(characterId: number) {
    const character = await this.characterRepository.findOne({
      where: { id: characterId },
      relations: ["detailedAttributes"],
    });

    if (!character) {
      return null;
    }

    // 返回抗性信息
    return {
      k_wl: character.detailedAttributes?.k_wl || 0,
      k_wei: character.detailedAttributes?.k_wei || 0,
      k_feng: character.detailedAttributes?.k_feng || 0,
      k_fa: character.detailedAttributes?.k_fa || 0,
      k_du: character.detailedAttributes?.k_du || 0,
      k_xi: character.detailedAttributes?.k_xi || 0,
      k_luan: character.detailedAttributes?.k_luan || 0,
      k_yao: character.detailedAttributes?.k_yao || 0,
      k_ll: character.detailedAttributes?.k_ll || 0,
      r_bj: character.detailedAttributes?.r_bj || 0,
      r_fj: character.detailedAttributes?.r_fj || 0,
      r_fz: character.detailedAttributes?.r_fz || 0,
      r_hb: character.detailedAttributes?.r_hb || 0,
      r_mf: character.detailedAttributes?.r_mf || 0,
      r_mz: character.detailedAttributes?.r_mz || 0,
      r_zm: character.detailedAttributes?.r_zm || 0,
    };
  }

  /**
   * 修改称号 (c:10011)
   */
  async modifyTitle(characterId: number, titleId: string, type: number) {
    if (type === 1) {
      // 设置称号
      const title = await this.getTitleById(parseInt(titleId));
      if (!title) {
        throw new Error("称号不存在");
      }
      await this.characterRepository.update(characterId, { title: title.name });
      return { title: title.name };
    } else {
      // 移除称号
      await this.characterRepository.update(characterId, { title: "" });
      return { title: "" };
    }
  }

  /**
   * 获取副将装备信息 (c:1130)
   */
  async getSubordinateEquipment(characterId: number) {
    // 这里应该从装备表获取，暂时返回空数据
    return {
      neck: null, // 项链
      left_hand: null, // 护腕
      head: null, // 头盔
      foot: null, // 战靴
      right_hand: null, // 武器
      body: null, // 铠甲
    };
  }

  /**
   * 获取技能列表 (c:1382) - 已废弃，请使用CharacterSkillService
   * @deprecated 请使用CharacterSkillService.getCharacterSkills()
   */
  async getSkillList(characterId: number) {
    // 这个方法已废弃，现在通过CharacterSkillService处理
    // 返回空数组，实际技能查询由1382指令处理器完成
    return [];
  }

  /**
   * 根据ID获取称号
   */
  private async getTitleById(titleId: number) {
    const titles = await this.getTitleList();
    return titles.find((title) => title.id === titleId);
  }

  /**
   * 创建默认角色数据
   */
  async createDefaultCharacter(
    userId: number,
    name: string,
    roleType: number,
    sex: number
  ) {
    // 获取当前最大角色ID，确保从2001开始
    const maxCharacter = await this.characterRepository
      .createQueryBuilder("character")
      .select("MAX(character.id)", "maxId")
      .getRawOne();

    const nextId = Math.max(2001, (maxCharacter?.maxId || 2000) + 1);

    // 创建角色，手动设置ID和时间字段
    const character = this.characterRepository.create({
      id: nextId,
      userId,
      name,
      roleType,
      sex,
      lvl: 1,
      exp: 0,
      trans: 0,
      title: "",
      vip: 0,
      allowLogin: 1,
      objType: 0,
      indexID: 0,
      created_at: new Date(),
      updated_at: new Date(),
    });

    const savedCharacter = await this.characterRepository.save(character);

    // 创建默认属性
    const attributes = this.attributeRepository.create({
      characterId: savedCharacter.id,
      hp: 300,
      maxHp: 300,
      mp: 100,
      maxMp: 100,
      ap: 80,
      df: 40,
      sp: 10,
      weight: 0,
      maxWeight: 100,
      hyd: 100,
      sinew: 100,
      p: 0,
      speedStr: "一",
    });

    await this.attributeRepository.save(attributes);

    // 创建默认详细属性
    const detailedAttributes = this.detailedAttributeRepository.create({
      characterId: savedCharacter.id,
    });

    await this.detailedAttributeRepository.save(detailedAttributes);

    // 创建默认技能 - 现在通过CharacterSkillService处理
    // 技能将在角色选择时自动创建，这里不再创建旧格式的技能记录

    // 创建默认社交关系
    const socialRelations = this.socialRelationRepository.create({
      characterId: savedCharacter.id,
    });

    await this.socialRelationRepository.save(socialRelations);

    // 创建默认资源记录
    const resources = this.resourcesRepository.create({
      characterId: savedCharacter.id,
      gold: 0,
      silver: 0,
      bdSilver: 0,
      fc: 0,
      superHK: 0,
      tlz: 0,
      tlzs: 0,
      vipBag: 0,
    });

    await this.resourcesRepository.save(resources);

    return savedCharacter;
  }

  /**
   * 获取用户的所有角色
   */
  async getUserCharacters(userId: number) {
    const characters = await this.characterRepository.find({
      where: { userId, allowLogin: 1 }, // 只返回允许登录的角色
      relations: ["attributes"],
    });

    return characters.map((character) => ({
      id: character.id,
      name: character.name,
      roleType: character.roleType,
      sex: character.sex,
      lvl: character.lvl,
      exp: character.exp,
      trans: character.trans,
      title: character.title,
      vip: character.vip,
      headImg: character.headImg,
      allowLogin: character.allowLogin,
      objType: character.objType,
      indexID: character.indexID,
      hp: character.attributes?.hp || 300,
      maxHp: character.attributes?.maxHp || 300,
      mp: character.attributes?.mp || 100,
      maxMp: character.attributes?.maxMp || 100,
    }));
  }
  /**
   * 创建新角色（用于WebSocket code:5）
   * 使用事务确保数据一致性，同时创建角色位置数据
   */
  async createNewRole(
    userId: number,
    roleData: {
      sex: number;
      roleType: number;
      headIndex?: number;
      name?: string;
    }
  ) {
    const { sex, roleType, headIndex = 2, name } = roleData;

    // 验证参数
    if (sex === undefined || roleType === undefined) {
      throw new Error("性别和职业类型不能为空");
    }

    // 验证性别范围
    if (sex !== 0 && sex !== 1) {
      throw new Error("性别值无效");
    }

    // 验证职业类型范围
    if (roleType < 1 || roleType > 3) {
      throw new Error("职业类型无效");
    }

    // 生成角色名称
    const roleName = name || this.generateDefaultRoleName(roleType, sex);

    // 使用事务创建角色和位置数据
    return await this.dataSource.transaction(async (manager) => {
      // 创建角色
      const character = await this.createDefaultCharacter(
        userId,
        roleName,
        roleType,
        sex
      );

      // 设置头像索引
      if (headIndex !== undefined) {
        await manager.update(CharacterEntity, character.id, {
          headImg: `head_${headIndex}`,
        });
      }

      // 创建角色位置数据（默认在新手村，area_id = 2）
      const characterLocation = new CharacterLocationEntity();
      characterLocation.characterId = character.id;
      characterLocation.areaId = 2; // 新手村
      characterLocation.lastMoveTime = new Date();
      characterLocation.isOnline = 1; // 在线
      characterLocation.lastOnlineTime = new Date();

      await manager.save(CharacterLocationEntity, characterLocation);

      return {
        id: character.id,
        name: character.name,
        roleType: character.roleType,
        sex: character.sex,
        lvl: character.lvl,
        exp: character.exp,
        trans: character.trans,
        title: character.title,
        vip: character.vip,
        headImg: character.headImg || `head_${headIndex}`,
        allowLogin: character.allowLogin,
        objType: character.objType,
        indexID: character.indexID,
        headIndex: headIndex,
        location: {
          areaId: 2,
          areaName: "新手村",
          isOnline: 1,
          lastMoveTime: characterLocation.lastMoveTime,
          lastOnlineTime: characterLocation.lastOnlineTime,
        },
      };
    });
  }
  /**
   * 生成默认角色名称
   */
  private generateDefaultRoleName(roleType: number, sex: number): string {
    const roleNames: Record<number, Record<number, string>> = {
      1: { 0: "女武士", 1: "男武士" },
      2: { 0: "女文人", 1: "男文人" },
      3: { 0: "女异师", 1: "男异师" },
    };

    const baseName = roleNames[roleType]?.[sex] || "角色";
    const randomSuffix = Math.floor(Math.random() * 1000);

    return `${baseName}${randomSuffix}`;
  }

  /**
   * 创建或更新角色资源
   */
  async createOrUpdateCharacterResources(
    characterId: number,
    resourceData: {
      gold?: number;
      silver?: number;
      bdSilver?: number;
      fc?: number;
      superHK?: number;
      tlz?: number;
      tlzs?: number;
      vipBag?: number;
    }
  ) {
    // 查找现有资源记录
    let resources = await this.resourcesRepository.findOne({
      where: { characterId },
    });

    if (resources) {
      // 更新现有记录（按 characterId 条件更新，避免将 characterId 误当作主键 id）
      await this.resourcesRepository.update(
        { characterId },
        {
          ...resourceData,
          updated_at: new Date(),
        }
      );
    } else {
      // 创建新记录
      resources = this.resourcesRepository.create({
        characterId,
        ...resourceData,
        created_at: new Date(),
        updated_at: new Date(),
      });
      await this.resourcesRepository.save(resources);
    }

    return resources;
  }

  /**
   * 获取角色资源信息
   */
  async getCharacterResources(characterId: number) {
    return await this.resourcesRepository.findOne({
      where: { characterId },
    });
  }

  /**
   * 更新角色资源（增量更新）
   */
  async updateCharacterResources(
    characterId: number,
    resourceData: {
      gold?: number;
      silver?: number;
      bdSilver?: number;
      fc?: number;
      superHK?: number;
      balanceGold?: number;
      balanceMoney?: number;
      tlz?: number;
      tlzs?: number;
      vipBag?: number;
    }
  ) {
    const resources = await this.getCharacterResources(characterId);

    if (!resources) {
      // 如果不存在，创建默认资源记录
      return await this.createOrUpdateCharacterResources(
        characterId,
        resourceData
      );
    }

    // 增量更新
    const updateData: any = { updated_at: new Date() };

    if (resourceData.gold !== undefined) {
      updateData.gold = resources.gold + resourceData.gold;
    }
    if (resourceData.silver !== undefined) {
      updateData.silver = resources.silver + resourceData.silver;
    }
    if (resourceData.bdSilver !== undefined) {
      updateData.bdSilver = resources.bdSilver + resourceData.bdSilver;
    }
    if (resourceData.balanceGold !== undefined) {
      updateData.balanceGold = resources.balanceGold + resourceData.balanceGold;
    }
    if (resourceData.balanceMoney !== undefined) {
      updateData.balanceMoney =
        resources.balanceMoney + resourceData.balanceMoney;
    }
    if (resourceData.fc !== undefined) {
      updateData.fc = resources.fc + resourceData.fc;
    }
    if (resourceData.superHK !== undefined) {
      updateData.superHK = resources.superHK + resourceData.superHK;
    }
    if (resourceData.tlz !== undefined) {
      updateData.tlz = resources.tlz + resourceData.tlz;
    }
    if (resourceData.tlzs !== undefined) {
      updateData.tlzs = resources.tlzs + resourceData.tlzs;
    }
    if (resourceData.vipBag !== undefined) {
      updateData.vipBag = resources.vipBag + resourceData.vipBag;
    }

    // 按 characterId 条件更新增量后的资源
    await this.resourcesRepository.update({ characterId }, updateData);
    return await this.getCharacterResources(characterId);
  }

  /**
   * 获取角色属性信息
   */
  async getCharacterAttributes(characterId: number) {
    return await this.attributeRepository.findOne({
      where: { characterId },
    });
  }

  /**
   * 获取角色详细属性信息
   */
  async getCharacterDetailedAttributes(characterId: number) {
    return await this.detailedAttributeRepository.findOne({
      where: { characterId },
    });
  }

  /**
   * 获取玩家金币信息 (1451接口)
   * 根据userId(characterId)获取该用户当前选中角色的金币信息
   */
  async getPlayerGold(characterId: number): Promise<any> {
    try {
      // 获取角色资源信息
      const resources = await this.getCharacterResources(characterId);

      if (!resources) {
        // 如果资源记录不存在，创建默认资源记录
        await this.createOrUpdateCharacterResources(characterId, {
          gold: 0,
          silver: 0,
          bdSilver: 0,
        });

        return {
          act_id: 1451,
          code: 0,
          data: {
            characterId: characterId,
            gold: 0,
            money: 0, // money字段对应银两
          },
        };
      }

      return {
        act_id: 1451,
        code: 0,
        data: {
          characterId: characterId,
          gold: resources.gold || 0,
          money: resources.silver || 0, // money字段对应银两
        },
      };
    } catch (error: any) {
      throw new Error(`获取玩家金币信息失败: ${error.message}`);
    }
  }

  /**
   * 获取玩家完整信息 (1020接口)
   * @param userId 用户ID
   * @returns 玩家完整信息
   */
  async getPlayerFullInfo(userId: number) {
    try {
      // 获取角色基本信息
      const character = await this.getCharacterById(userId);
      if (!character) {
        return null;
      }

      // 获取计算后的角色属性信息（使用characterAttributeService）
      const basicAttributes =
        await this.characterAttributeService.getCharacterBasicAttributes(
          userId
        );

      // 获取副将列表
      const deputyGenerals = await this.getCharacterDeputyGenerals(userId);

      // 获取魂蛋列表
      const stones = await this.getCharacterStones(userId);

      // 获取坐骑信息
      const horse = await this.getCharacterHorse(userId);

      // 获取房屋信息（与 1480 一致结构）
      const houseInfo = await this.getCharacterHouse(userId);

      // 获取教派信息
      const religion = await this.getCharacterReligion(userId);

      // 获取配偶信息
      const spouse = await this.getCharacterSpouse(userId);

      // 获取师父信息
      const master = await this.getCharacterMaster(userId);

      // 获取 VIP 等级（数据库 vip_status）
      let vipLvl = -1;
      try {
        const info = await (this as any).vipService?.queryVipInfo(userId, -2);
        vipLvl = info?.vipLvl ?? -1;
      } catch {}

      // 构建返回数据
      return {
        id: character.id,
        name: character.name,
        roleType: character.roleType,
        sex: character.sex,
        lvl: character.lvl,
        trans: character.trans || 0,
        title: character.title || "无",
        vip: vipLvl,
        img: character.headImg || "ws2.jpg",
        commentary: "无", // 固定值
        remark: "", // 固定值
        stall: "无", // 固定值
        pkFlag: 0, // 固定值
        online: await this.getCharacterOnlineStatus(character.id), // 从Redis获取在线状态
        friend: 0, // 固定值
        friendNum: 0, // 固定值
        black: 0, // 固定值
        kill: 3, // 固定值
        distinction: 3, // 固定值
        charm: -1, // 固定值
        // 基础属性 - 使用计算后的属性值
        hp: basicAttributes?.hp || 0,
        maxHp: basicAttributes?.maxHp || 0,
        mp: basicAttributes?.mp || 0,
        maxMp: basicAttributes?.maxMp || 0,
        ap: basicAttributes?.ap || 0,
        df: basicAttributes?.df || 0,
        sp: basicAttributes?.sp || 0,
        hyd: basicAttributes?.hyd || 0,
        // 副将列表 - 使用真实数据，如果没有则返回空数组
        cortegeList:
          deputyGenerals.length > 0
            ? deputyGenerals.map((dg: any) => ({
                id: dg.id,
                name: dg.name,
              }))
            : [],
        // 魂蛋列表 - 使用真实数据，如果没有则返回空数组
        stoneList:
          stones.length > 0
            ? stones.map((stone: any) => ({
                id: stone.id,
                name: stone.name,
              }))
            : [],
        // 坐骑信息 - 使用真实数据，如果没有则返回默认对象
        horse: horse
          ? {
              id: horse.id,
              name: horse.name,
            }
          : { id: 0, name: "无" },
        // 房屋信息 - 使用真实数据，如果没有则返回默认对象
        house: houseInfo
          ? { r: houseInfo.r, lvl: houseInfo.lvl, name: houseInfo.n }
          : { r: 0, lvl: 0, name: "无" },
        // 教派信息 - 使用真实数据，如果没有则返回默认对象
        religion: religion
          ? {
              id: religion.id,
              name: religion.name,
            }
          : { id: 0, name: "无" },
        // 配偶信息 - 使用真实数据，如果没有则返回默认对象
        spouse: spouse
          ? {
              id: spouse.id,
              name: spouse.name,
            }
          : { id: 0, name: "无" },
        // 师父信息 - 使用真实数据，如果没有则返回默认对象
        master: master
          ? {
              id: master.id,
              name: master.name,
            }
          : { id: 0, name: "无" },
        // 关系状态
        relation: "无", // 固定值
      };
    } catch (error: any) {
      console.error("获取玩家完整信息失败:", error);
      throw new Error(`获取玩家完整信息失败: ${error.message}`);
    }
  }

  /**
   * 获取角色在线状态
   */
  async getCharacterOnlineStatus(characterId: number): Promise<string> {
    try {
      // 从Redis中获取角色在线状态
      const onlineStatus = await this.redisService.get(
        `character:online:${characterId}`
      );
      if (onlineStatus) {
        return "在线";
      }

      // 检查是否在在线角色集合中
      const isInOnlineSet = await this.redisService.sismember(
        "online_characters",
        characterId.toString()
      );
      if (isInOnlineSet) {
        return "在线";
      }

      return "离线";
    } catch (error) {
      console.error(`获取角色 ${characterId} 在线状态失败:`, error);
      return "离线"; // 出错时默认为离线
    }
  }

  /**
   * 获取角色副将列表
   */
  async getCharacterDeputyGenerals(characterId: number): Promise<any[]> {
    try {
      // 调用副将服务获取上阵的副将列表（只获取已上阵的副将）
      const result = await this.deputyGeneralService.getDeputyList(
        characterId,
        true
      );
      return result.list || [];
    } catch (error) {
      console.error("获取副将列表失败:", error);
      return [];
    }
  }

  /**
   * 1409：查询可学习技能的副将列表（最多10个）
   */
  async getDeputiesForSkillLearn(characterId: number, pageNum: number = 0) {
    const result = await this.deputyGeneralService.getDeputyList(characterId);
    const list = (result.list || []).map((d: any) => ({
      id: d.id,
      lvl: d.lvl,
      name: d.name,
      pos: d.pos,
      roleType: d.roleType,
      s: d.s,
      skill: Number(d.skill || 0),
    }));
    return list;
  }

  /**
   * 2020：查询可用此技能书的目标（-9 自身 + 副将）
   */
  async getSkillBookTargets(
    characterId: number,
    gid: number,
    pageNum: number = 0
  ) {
    const deputies = await this.getCharacterDeputyGenerals(characterId);
    const list: Array<{ id: number; name: string }> = [
      { id: -9, name: "自身" },
      ...deputies.map((d: any) => ({
        id: d.id,
        name: `${d.name}(${d.lvl} 级)`,
      })),
    ];
    return list;
  }

  /**
   * 2021：查询目标可用此技能书的技能列表
   */
  async getSkillsForBook(
    characterId: number,
    gid: number,
    cid: number,
    pageNum: number = 0
  ) {
    // 简化：当前返回已拥有的技能供加熟练度；后续可按技能书等级过滤
    if (cid === -9) {
      const skills = await this.characterSkillService.getCharacterSkills(
        characterId
      );
      return skills.map((s: any) => ({
        id: s.skillId,
        name: `${s.skillName}(${s.grade} 级)`,
      }));
    }
    // 副将
    const deputy = await this.deputyGeneralService.getDeputyAttributes(
      cid,
      characterId
    );
    const list = Array.isArray(deputy?.skillList)
      ? deputy.skillList.map((s: any) => ({
          id: s.id,
          name: `${s.name}(${s.grade} 级)`,
        }))
      : [];
    return list;
  }

  /**
   * 2022：使用技能书，消耗背包道具并增加熟练度
   */
  async useSkillBook(
    characterId: number,
    gid: number,
    cid: number,
    sid: number,
    count: number
  ) {
    // 扣除背包 gid 数量 count
    const invSvc: any = (this as any).inventoryService;
    const inv = await invSvc.getCharacterInventoryItem(characterId, gid);
    if (!inv || (inv.num || 0) < count)
      throw new Error("背包中该技能书数量不足");
    await invSvc.discardItemFromInventory(characterId, gid, count);

    // 每本技能书增加熟练度 100（可拓展为按gid映射）
    const delta = 100 * Math.max(1, Number(count || 1));
    let current = 0;
    if (cid === -9) {
      const skill = await this.characterSkillService.getCharacterSkill(
        characterId,
        sid
      );
      if (!skill) throw new Error("技能不存在");
      current = Number(skill.useCount || 0);
      await this.characterSkillService.addSkillProficiency(
        characterId,
        sid,
        delta
      );
      return `${skill.grade} 级技能${
        skill.skillName
      }已提高 ${delta} 熟练度，消耗了 ${count} 本技能书，现熟练度为 ${
        current + delta
      }`;
    }
    // 副将：更新副将技能表 use_count
    const mgr = this.deputyGeneralService as any;
    const depSkill = await (
      mgr as any
    ).deputyGeneralSkillLearnedRepository.findOne({
      where: { deputy_id: cid, skill_id: sid },
    });
    if (!depSkill) throw new Error("副将技能不存在");
    current = Number(depSkill.use_count || 0);
    await (mgr as any).deputyGeneralSkillLearnedRepository.update(
      { deputy_id: cid, skill_id: sid },
      { use_count: current + delta, updated_at: new Date() }
    );
    return `${depSkill.grade} 级技能${
      depSkill.skill?.name || "技能"
    }已提高 ${delta} 熟练度，消耗了 ${count} 本技能书，现熟练度为 ${
      current + delta
    }`;
  }

  /**
   * 获取角色魂蛋列表
   */
  async getCharacterStones(characterId: number): Promise<any[]> {
    try {
      // 查询角色的魂蛋信息
      const stones = await this.stoneRepository.find({
        where: { characterId },
      });

      return stones.map((stone) => ({
        id: stone.id,
        name: stone.name || "未知魂蛋",
      }));
    } catch (error: any) {
      this.logger.error(`获取角色魂蛋列表失败: ${error?.message || error}`);
      return [];
    }
  }

  /**
   * 获取角色坐骑信息
   */
  async getCharacterHorse(characterId: number): Promise<any | null> {
    try {
      // 查询角色的坐骑信息（上阵状态的坐骑）
      const mount = await this.characterMountRepository.findOne({
        where: { characterId, status: 2 }, // 2-出战状态
        relations: ["mountBase"],
      });

      if (mount && mount.mountBase) {
        return {
          id: mount.id,
          name: mount.mountBase.name || "未知坐骑",
        };
      }

      return null;
    } catch (error: any) {
      this.logger.error(`获取角色坐骑信息失败: ${error?.message || error}`);
      return null;
    }
  }

  /**
   * 获取角色房屋信息
   */
  async getCharacterHouse(characterId: number): Promise<any | null> {
    try {
      const residence = await this.residenceRepository.findOne({
        where: { characterId },
      });
      if (!residence) {
        return null;
      }
      const lvl = residence.houseLevel || 0;
      // 剩余修炼次数 r：按每日计数表 character_heal_claim 计算（当日最大=houseLevel 1-5）
      let r = lvl;
      try {
        const today = new Date();
        const yyyy = today.getFullYear();
        const mm = String(today.getMonth() + 1).padStart(2, "0");
        const dd = String(today.getDate()).padStart(2, "0");
        const dateStr = `${yyyy}-${mm}-${dd}`;
        const repo = this.dataSource.getRepository(
          (await import("../entities/character-heal-claim.entity"))
            .CharacterHealClaimEntity
        );
        const row = await repo.findOne({
          where: { characterId, claimDate: dateStr },
        });
        const used = row?.usedCount || 0;
        const maxTimes = Math.max(1, Math.min(5, lvl));
        r = Math.max(0, maxTimes - used);
      } catch {}
      const n = residence.houseName || (lvl === 0 ? "未购房" : `${lvl}级房`);
      const homeName = residence.homeName || "未知区域"; // 购房地点
      return { r, lvl, n, homeName };
    } catch (error: any) {
      this.logger.error(`获取角色房屋信息失败: ${error?.message || error}`);
      return null;
    }
  }

  /** 获取角色当前所在区域名称 */
  async getCharacterAreaName(characterId: number): Promise<string> {
    try {
      const loc = await this.characterLocationRepository.findOne({
        where: { characterId },
        relations: ["area"],
      });
      return loc?.area?.name || "未知区域";
    } catch (error: any) {
      this.logger.error(
        `获取角色当前区域名称失败: ${error?.message || String(error)}`
      );
      return "未知区域";
    }
  }

  /** 购房（购买1级房，1980金） */
  async purchaseHouse(
    characterId: number
  ): Promise<{ code: number; msg: string }> {
    try {
      let residence = await this.residenceRepository.findOne({
        where: { characterId },
      });
      if (!residence) {
        // 从位置服务推断当前区域名称
        let currentAreaName = "未知区域";
        try {
          const loc = await this.characterLocationRepository.findOne({
            where: { characterId },
            relations: ["area"],
          });
          if (loc?.area?.name) currentAreaName = loc.area.name;
        } catch {}
        residence = this.residenceRepository.create({
          characterId,
          homeName: currentAreaName,
          homeLevel: 1,
          houseName: "",
          houseLevel: 0,
          horseName: "",
          horseLevel: 0,
          created_at: new Date(),
          updated_at: new Date(),
        });
        await this.residenceRepository.save(residence);
      }
      if ((residence.houseLevel || 0) >= 1) {
        return { code: 8, msg: "已购买房产" };
      }
      const RES_COST = 1980;
      const res = await this.getCharacterResources(characterId);
      if (!res || (res.gold || 0) < RES_COST) {
        return { code: 8, msg: "您没有 1980 金币无法购买" };
      }
      // 扣金
      await this.resourcesRepository.update(
        { characterId },
        { gold: (res.gold || 0) - RES_COST, updated_at: new Date() }
      );
      // 设置为1级
      // 购房时同步最新居住地
      let currentAreaName = residence.homeName || "未知区域";
      try {
        const loc = await this.characterLocationRepository.findOne({
          where: { characterId },
          relations: ["area"],
        });
        if (loc?.area?.name) currentAreaName = loc.area.name;
      } catch {}
      await this.residenceRepository.update(
        { characterId },
        {
          homeName: currentAreaName,
          houseLevel: 1,
          houseName: "平房",
          updated_at: new Date(),
        }
      );
      return { code: 0, msg: "购买成功" };
    } catch (error: any) {
      this.logger.error(`购房失败: ${error?.message || error}`);
      return { code: -1, msg: error?.message || "购房失败" };
    }
  }

  /** 升级房子（按档位扣金：2级2980、3级3980、4级4980、5级5980） */
  async upgradeHouse(
    characterId: number
  ): Promise<{ code: number; msg: string }> {
    try {
      const residence = await this.residenceRepository.findOne({
        where: { characterId },
      });
      const cur = residence?.houseLevel || 0;
      if (cur <= 0) return { code: 8, msg: "未购买房产" };
      if (cur >= 5) return { code: 8, msg: "已达最高等级" };
      const next = cur + 1;
      const COSTS: Record<number, { cost: number; name: string }> = {
        2: { cost: 2980, name: "楼房" },
        3: { cost: 3980, name: "loft" },
        4: { cost: 4980, name: "别墅" },
        5: { cost: 5980, name: "花园洋房" },
      };
      const cfg = COSTS[next];
      const res = await this.getCharacterResources(characterId);
      if (!res || (res.gold || 0) < cfg.cost) {
        return { code: 8, msg: `您没有 ${cfg.cost} 金币无法升级` };
      }
      await this.resourcesRepository.update(
        { characterId },
        { gold: (res.gold || 0) - cfg.cost, updated_at: new Date() }
      );
      await this.residenceRepository.update(
        { characterId },
        { houseLevel: next, houseName: cfg.name, updated_at: new Date() }
      );
      return { code: 0, msg: "升级成功" };
    } catch (error: any) {
      this.logger.error(`升级房子失败: ${error?.message || error}`);
      return { code: -1, msg: error?.message || "升级失败" };
    }
  }

  /**
   * 获取角色教派信息
   */
  async getCharacterReligion(characterId: number): Promise<any | null> {
    try {
      // 查询角色的教派信息
      const religion = await this.religionRepository.findOne({
        where: { characterId },
      });

      if (religion) {
        return {
          id: religion.id,
          name: religion.name || "未知教派",
        };
      }

      // 为测试用户2019返回模拟教派信息
      if (characterId === 2019) {
        console.log(`🎭 为测试用户${characterId}返回模拟教派信息`);
        return {
          id: 999,
          name: "测试教派_模拟数据",
        };
      }

      return null;
    } catch (error: any) {
      this.logger.error(`获取角色教派信息失败: ${error?.message || error}`);
      return null;
    }
  }

  /**
   * 获取角色配偶信息
   */
  async getCharacterSpouse(characterId: number): Promise<any | null> {
    // 这里应该调用社交关系服务，暂时返回null
    return null;
  }

  /**
   * 获取角色师父信息
   */
  async getCharacterMaster(characterId: number): Promise<any | null> {
    // 这里应该调用社交关系服务，暂时返回null
    return null;
  }

  /**
   * 软删除角色 (1475接口)
   * @param characterId 角色ID
   * @param userId 用户ID（用于验证权限）
   * @returns 删除结果
   */
  async softDeleteCharacter(
    characterId: number,
    userId: number
  ): Promise<{ success: boolean; message: string }> {
    try {
      // 1. 验证角色是否存在且属于当前用户
      const character = await this.characterRepository.findOne({
        where: { id: characterId },
      });

      if (!character) {
        return { success: false, message: "角色不存在" };
      }

      if (character.userId !== userId) {
        return { success: false, message: "无权删除此角色" };
      }

      // 2. 检查角色等级是否超过30级
      if (character.lvl > 30) {
        return { success: false, message: "等级超过30级的角色不允许删除" };
      }

      // 3. 执行软删除（设置allowLogin为0）
      await this.characterRepository.update(characterId, {
        allowLogin: 0,
        updated_at: new Date(),
      });

      return { success: true, message: "角色删除成功" };
    } catch (error: any) {
      console.error("软删除角色失败:", error);
      return { success: false, message: `删除失败: ${error.message}` };
    }
  }

  /**
   * 更新角色银币
   */
  async updateSilver(characterId: number, silverChange: number): Promise<void> {
    try {
      // 银币存储在CharacterResourcesEntity中，不是CharacterEntity中
      // 这个方法应该被移除，因为银币更新应该在CharacterResourcesService中处理
      throw new Error(
        "银币更新应该在CharacterResourcesService中处理，而不是CharacterService"
      );
    } catch (error: any) {
      console.error("更新角色银币失败:", error);
      throw new Error(`更新银币失败: ${error.message}`);
    }
  }
}
